/* $Id$ */
package org.crazydays.gameplan;


import java.awt.Frame;
import java.io.File;
import java.io.IOException;

import javax.swing.JFileChooser;
import javax.swing.filechooser.FileNameExtensionFilter;

import org.crazydays.gameplan.map.IGameMap;
import org.crazydays.gameplan.map.swing.JCreateMapDialog;
import org.crazydays.gameplan.model.Model;
import org.crazydays.gameplan.swing.JAboutDialog;
import org.crazydays.gameplan.view.View;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Controller
 */
public class Controller
{
    /** logger */
    protected final static Logger LOGGER =
        LoggerFactory.getLogger(Controller.class);

    /** model */
    protected Model model;

    /** view */
    protected View view;

    /** actions */
    protected Actions actions;

    /**
     * Controller constructor.
     * 
     * @param model Model
     */
    public Controller(Model model)
    {
        this.model = model;
    }

    /**
     * Initialize.
     */
    public void initialize()
    {
        initializeActions();
        initializeView();
    }

    /**
     * Initialize actions.
     */
    protected void initializeActions()
    {
        actions = new Actions(this);
        actions.initialize();
        model.addDatabaseObserver(actions);
    }

    /**
     * Initialize view.
     */
    protected void initializeView()
    {
        view = new View(this, model);
        view.initialize();
        model.addDatabaseObserver(view);
    }

    /**
     * Get view.
     * 
     * @return View
     */
    public View getView()
    {
        return this.view;
    }

    /**
     * Get actions.
     * 
     * @return Actions
     */
    public Actions getActions()
    {
        return actions;
    }

    /**
     * Create database.
     */
    public void createDatabase()
    {
        // TODO: close out existing database
        model.createDatabase();
    }

    /**
     * Close current database.
     */
    public void closeDatabase()
    {
        model.closeDatabase();
    }

    /**
     * Add game map.
     * 
     * @param gameMap GameMap
     */
    public void addGameMap(IGameMap gameMap)
    {
        model.addGameMap(gameMap);
    }

    /**
     * Open game map.
     * 
     * @param name Name
     */
    public void openGameMap(String name)
    {
        IGameMap gameMap = model.getGameMap(name);
        if (gameMap != null) {
            view.open(gameMap);
        }
    }

    /**
     * Save model.
     * 
     * @param file File
     */
    public void save(boolean saveAs)
    {
        if (saveAs || !model.isSaveFileSet()) {
            if (!promptForSaveFile()) {
                // TODO: oops, try again
                return;
            }
        }

        try {
            model.save();
        } catch (IOException e) {
            LOGGER.warn("Unable to save database: {0}", e);
        }
    }

    /**
     * Prompt for save file.
     * 
     * @return Valid save file
     */
    protected boolean promptForSaveFile()
    {
        JFileChooser chooser = new JFileChooser();

        FileNameExtensionFilter filter =
            new FileNameExtensionFilter("GamePlan Database File", "gp1");

        chooser.setFileFilter(filter);

        if (chooser.showOpenDialog(view) == JFileChooser.APPROVE_OPTION) {
            File file = chooser.getSelectedFile();
            if (file != null) {
                model.setSaveFile(file);
            }
        }

        return model.isSaveFileSet();
    }

    /**
     * Open database.
     */
    public void openDatabase()
    {
        File file = promptForOpenFile();
        if (file != null) {
            try {
                model.openDatabase(file);
            } catch (IOException e) {
                LOGGER.warn("Unable to open database {0}", e);
            }
        }
    }

    /**
     * Prompt for open file.
     * 
     * @return File
     */
    protected File promptForOpenFile()
    {
        JFileChooser chooser = new JFileChooser();

        FileNameExtensionFilter filter =
            new FileNameExtensionFilter("GamePlan Database File", "gp1");

        chooser.setFileFilter(filter);

        if (chooser.showOpenDialog(view) == JFileChooser.APPROVE_OPTION) {
            return chooser.getSelectedFile();
        } else {
            LOGGER.warn("No file selected");
            return null;
        }
    }

    /**
     * Open create map dialog.
     */
    public void openCreateMapDialog()
    {
        JCreateMapDialog createMapDialog = new JCreateMapDialog(this);

        createMapDialog.initialize();
        createMapDialog.setAlwaysOnTop(true);
        createMapDialog.setVisible(true);
    }

    /**
     * Open about dialog.
     */
    public void openAboutDialog()
    {
        JAboutDialog aboutDialog = new JAboutDialog((Frame) view.getParent());
        aboutDialog.setAlwaysOnTop(true);
        aboutDialog.setVisible(true);
    }

    /**
     * Toggle grid.
     * 
     * @return Grid visible
     */
    public boolean toggleGrid()
    {
        return view.toggleGrid();
    }
}
